package FileProcess;
//import java.io.BufferedInputStream;
//import java.io.DataInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
//import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import org.json.*;
//import ObjStructure.Text;
import ObjStructure.Product;
import DataPreprocess.CleanStopWords;
import DataPreprocess.CleanStemmingWords;

public class JsonRead 
{
	private CleanStopWords cleanStopWords = null;
	private CleanStemmingWords cleanStemmingWords = null;
	private String dirPath_storeArticle = null;
	private int hashPkey = 0;													//number of Product
	private Map<Integer, Product> Productmap 
		= new HashMap<Integer, Product>();										//hash map for Product
	private Hashtable<String, Hashtable<String,ArrayList<Integer>>> Texthash
		= new Hashtable<String, Hashtable<String,ArrayList<Integer>>>();		//hashtable mapping key to a hashtable that include all text token
	public Map<Integer, Product> getPmap()										//get product hash 
	{
		return Productmap;
	}
	public Hashtable<String, Hashtable<String,ArrayList<Integer>>> getTtable()	//get Text hash
	{
		return Texthash;
	}
	

	public JsonRead(String dirPath_storeArticle)
	{
		//initial variable
		if(dirPath_storeArticle.lastIndexOf("/")!=dirPath_storeArticle.length()-1)
			dirPath_storeArticle = dirPath_storeArticle + "/";
		this.dirPath_storeArticle = dirPath_storeArticle;
		this.cleanStopWords = new CleanStopWords("table/stopword.txt", 27);
		this.cleanStemmingWords = new CleanStemmingWords();
	}
	/** store Product JsonItem **/
	private void _001_storeJsonItemProduct(String id, JSONArray list_item)
	{	
		try 
		{
			Product prod = new Product(id,list_item.get(0).toString(), list_item.get(1).toString(), list_item.get(2).toString());
			Productmap.put(hashPkey, prod);
		} 
		catch (JSONException e) { e.printStackTrace();}
		hashPkey++;
	}
	public void _002_storeJsonItemText(String id, JSONArray list_item)						//data structure load the TextItem
	{
		String getStr = null;
		boolean isAdd = true;
		try 
		{
			Hashtable<String,ArrayList<Integer>> innerTable 
				= new Hashtable<String,ArrayList<Integer>>();
			for(int i = 0;i<list_item.length();i++)
			{
				//get each string
				getStr = list_item.get(i).toString();
				//judge whether this word is a stop word
				isAdd = !this.cleanStopWords.ACT001_judgeWordIsStopWord(getStr);
				//add this word to hash if isAdd is equall to true
				if(isAdd)
				{
					//do stemming
					getStr = this.cleanStemmingWords.ACT001_doStemming(getStr);
					//add word to hash
					ArrayList<Integer> list = new ArrayList<Integer>();
					if(innerTable.containsKey(getStr))						//if the key is in innertable
						list = innerTable.get(getStr);						//'add' index of the key to the arraylist
					list.add(i);																//else just put the index
					innerTable.put( getStr,list);
				}
				isAdd = true;
			}
			Texthash.put(id,innerTable);
		} 
		catch (JSONException e) { e.printStackTrace(); }
	}
	private void _003_showProductResult()
	{
		System.out.println("\n-------------------Show Load Product Result-------------------");
		int index = 0;
		while(index < this.Productmap.size())
		{
			this.Productmap.get(index).printInString();
			index = index + 1;
		}
	}
	private void _004_showTextResult()
	{
		System.out.println("-------------------Show Load TextItem Result-------------------");
		int indexText = 0, indexToken = 0, indexList = 0;
		Enumeration<String> a = this.Texthash.keys();
		while(indexText < this.Texthash.size())
		{
			String key_article = a.nextElement();
			System.out.print(key_article + " ------>" + "\n");
			Hashtable<String, ArrayList<Integer>> hash_article = this.Texthash.get(key_article);
			Enumeration<String> b = hash_article.keys();
			indexToken = 0;
			while(indexToken < hash_article.size())
			{
				String key_token = b.nextElement();
				System.out.print(key_token + " : ");
				ArrayList list = (ArrayList)hash_article.get(key_token);
				indexList = 0;
				while(indexList < list.size())
				{
					System.out.print(list.get(indexList) + " ");
					indexList = indexList + 1;
				}
				indexToken = indexToken + 1;
				System.out.println();
			}
			indexText = indexText + 1;
		}
	}

	public void _005_storeProductJsontoFile(String IDs,String pathname, JSONArray list_item)	//store json file token in files
	{
		String filename = pathname;
		try 
		{
			File file = new File(filename);
			FileWriter fr = new FileWriter(file,true);
			String get_str = null, store_str = IDs + "\n";
			String[] list_token = list_item.get(0).toString().split(" ");
			int index = 0;
			while(index < list_token.length)
			{
				get_str = list_token[index];
				if(!this.cleanStopWords.ACT001_judgeWordIsStopWord(get_str))
				{
					get_str = this.cleanStemmingWords.ACT001_doStemming(get_str);
					store_str = store_str + get_str + " ";
				}
				index = index + 1;
			}
			store_str.replace("-", " ");
			store_str += "\n";
			fr.write(store_str);
			fr.close();
		} 
		catch (IOException e) {	e.printStackTrace();}
		catch (JSONException e) { e.printStackTrace(); }
	}

	public String ACT001_readAllFromFIle(String filePath)
	{
		StringBuilder readStr = new StringBuilder("");
		StringBuilder readStrtemp = new StringBuilder("");
		FileReader fr = null;
                int errorIdAdd = 10000;
        BufferedReader br = null;
	    try 
	    {
	        fr = new FileReader(filePath);
	        br = new BufferedReader(fr);
                String str_readLine = "";
	        // dis.available() returns 0 if the file does not have more lines.
	        long index = 0;
	        while (br.ready()) 
	        {
	            // this statement reads the line from the file and print it to
	            // the console.
                    str_readLine = br.readLine();
                    if(str_readLine.compareTo("    \"\": [") == 0)    //process null title
                    {
                        str_readLine = "    \"" + errorIdAdd + "\": [";
                        errorIdAdd = errorIdAdd + 1;
                        System.out.println("Process null title");
                    }
	    	    readStr.append(str_readLine);
	    	    if(index % 100000 == 0)
	    	    {
                        System.out.println("read"+index);
	    	    	readStrtemp.append(readStr.toString());
	    	    	readStr = new StringBuilder("");
	    	    }
	    	    index ++;
	        }
	        readStrtemp.append(readStr.toString());
	        // dispose all the resources after using them.
	        fr.close();
	        br.close();
	    } 
	    catch (FileNotFoundException e) 
	    {
	      e.printStackTrace();
	    } 
	    catch (IOException e) 
	    {
	      e.printStackTrace();
	    }
	    return readStrtemp.toString();
	}
	public void ACT002_readJson(String filePath, String itemName)
	{
		//get full file string
		StringBuilder s = new StringBuilder("");
		s.append(this.ACT001_readAllFromFIle(filePath));
		JSONObject jobj_main = null, jobj_item = null;
		JSONArray list_keyName = null;
		int index_item = 0;
		try 
		{
                        System.out.println("Create json object");
			jobj_main = new JSONObject(s.toString());
                        System.out.println("Create json object finish");
			jobj_item = jobj_main.getJSONObject(itemName);
			list_keyName = jobj_item.names();
			index_item = 0;
			
			//create items dir
			String dirpath = this.dirPath_storeArticle;
			if(itemName.equals("Product"))		//product just don't care
			{
				File dir = new File(dirpath);	//if this dir doesn't exist then create one
				if(!dir.exists())
					dir.mkdirs();
				else if(dir.isDirectory())	//delete all file in this dir
				{
					File[] files = dir.listFiles();
					for (int i = 0 ;i<files.length;i++)
					{
						files[i].delete();
					}
				}
			}
			String path = dirpath + "products";
			
			while(index_item < jobj_item.length())
			{
				String key = list_keyName.getString(index_item);
                                if(index_item % 100000 == 0)
                                    System.out.println("build hash " + index_item);
				if(itemName.equals("Product"))
				{
					
					this._005_storeProductJsontoFile(key ,path, jobj_item.getJSONArray(key));
					this._001_storeJsonItemProduct(key, jobj_item.getJSONArray(key));
				}
				else
				{
					this._002_storeJsonItemText(key, jobj_item.getJSONArray(key));
					//this._004_showTextResult(key, jobj_item.getJSONArray(key));		//Test - print the Arraylist from double hash
					
				}
				index_item = index_item + 1;
			}
		} 
		catch (JSONException e)	{ e.printStackTrace(); }
	}
	public void ACT003_showResult()
	{
		//show text loading result
		this._004_showTextResult();
		//show product loading result
		this._003_showProductResult();
	}
	public static void main(String args[])
	{
		//check argument
		if(args.length != 3)
		{
			System.out.println("Error, you should input 3 argument - " +
					"<file path of text> <file path of produce> <dir path of storing each article>");
		}
		else
		{
			JsonRead r = new JsonRead(args[2]);
			//load data
			r.ACT002_readJson(args[0], "TextItem");
			r.ACT002_readJson(args[1], "Product");
			//testing result
			//r.ACT003_showResult();
		}
	}
}
